//********************************************************************
//	created:	15:10:2011   4:54
//	filename: 	apnservice.h
//	author:		tiamo
//	purpose:	apn service
//********************************************************************

#pragma once

namespace apn
{
	//
	// notification packet
	//
	class NotificationPacket : public network::BasePacket
	{
	public:
		//
		// constructor
		//
		NotificationPacket() : BasePacket(L"apn::NotificationPacket")		{}

		//
		// destructor
		//
		virtual ~NotificationPacket()										{}

		//
		// serialize
		//
		virtual void serialize(utils::DataBuffer& dataBuffer, bool readFromBuffer);

		//
		// get message length
		//
		static uint32_t getMessageLength(void const* dataBuffer, uint32_t dataLength);

	public:
		//
		// id
		//
		uint32_t															mId;

		//
		// expiry
		//
		uint32_t															mExpiry;

		//
		// device token
		//
		UniString															mDeviceToken;

		//
		// payload
		//
		UniString															mPayload;
	};

	//
	// result response packet
	//
	class ResultResponsePacket : public network::BasePacket
	{
	public:
		//
		// constructor
		//
		ResultResponsePacket() : BasePacket(L"apn::ResultResponsePacket")	{}

		//
		// destructor
		//
		virtual ~ResultResponsePacket()										{}

		//
		// serialize
		//
		virtual void serialize(utils::DataBuffer& dataBuffer, bool readFromBuffer);

		//
		// get message length
		//
		static uint32_t getMessageLength(void const* dataBuffer, uint32_t dataLength);

	public:
		//
		// status
		//
		uint8_t																mStatus;

		//
		// id
		//
		uint32_t															mId;
	};

	//
	// feedback packet
	//
	class FeedbackPacket : public network::BasePacket
	{
	public:
		//
		// constructor
		//
		FeedbackPacket() : BasePacket(L"apn::FeedbackPacket")				{}

		//
		// destructor
		//
		virtual ~FeedbackPacket()											{}

		//
		// serialize
		//
		virtual void serialize(utils::DataBuffer& dataBuffer, bool readFromBuffer);

		//
		// get message length
		//
		static uint32_t getMessageLength(void const* dataBuffer, uint32_t dataLength);

	public:
		//
		// time
		//
		uint32_t															mTime;

		//
		// device token
		//
		UniString															mDeviceToken;
	};

	//
	// notification
	//
	struct notification
	{
		//
		// id
		//
		uint32_t															mId;

		//
		// expire
		//
		int32_t																mExpire;

		//
		// device token
		//
		UniString															mDeviceToken;

		//
		// payload
		//
		UniString															mPayload;
	};

	//
	// apn service
	//
	class Service : public ::Service
	{
	public:
		//
		// constructor
		//
		Service(UniString const& name, mysql::Database& database, bool devMode) : ::Service(name, database), mDevMode(devMode) {}

		//
		// destructor
		//
		virtual ~Service()													{}

	private:
		//
		// initialize
		//
		virtual void initialize();

		//
		// create socket
		//
		void createSocket(bool apnSocket, uint32_t delayTime = 0);

		//
		// push notification timer
		//
		bool onPushNotificationTimer(uint32_t elapsedTime);

		//
		// load notification list
		//
		void onLoadNotification(utils::BaseRequest* theRequest);

		//
		// save result
		//
		void onSaveResult(utils::BaseRequest* theRequest);

		//
		// deactive device token
		//
		void onDeactiveDeviceToken(utils::BaseRequest* theRequest);

		//
		// socket connected
		//
		void onSocketConnected(network::AsyncSocket* theSocket, bool errorState);

		//
		// socket closed
		//
		void onSocketClosed(network::AsyncSocket* theSocket, bool errorState);

		//
		// socket decode packet
		//
		utils::SmartPointer<network::BasePacket> onSocketDecodePacket(network::AsyncSocket* theSocket, void const* dataBuffer, uint16_t dataLength, uint32_t& usedLength);

		//
		// socket data
		//
		void onSocketPacket(network::AsyncSocket* theSocket, network::BasePacket* thePacket);

	private:
		//
		// debug mode
		//
		bool																mDevMode;

		//
		// apn host
		//
		UniString															mApnHost;

		//
		// apn port
		//
		uint32_t															mApnPort;

		//
		// feedback host
		//
		UniString															mFeedbackHost;

		//
		// feedback host
		//
		uint32_t															mFeedbackPort;

		//
		// ca root
		//
		UniString															mCARoot;

		//
		// client cert
		//
		UniString															mClientCert;

		//
		// client key
		//
		UniString															mClientKey;

		//
		// apn socket
		//
		utils::SmartPointer<network::AsyncSocket>							mApnSocket;

		//
		// feedback socket
		//
		utils::SmartPointer<network::AsyncSocket>							mFeedbackSocket;

		//
		// cached list
		//
		std::list<notification>												mNotificationList;
	};
}
